#include "functions.h"

// Genrate min <= x < max - 1
int get_random_integer_value( const int min, const int max ){

  return ( int ) ( ( double ) rand() / RAND_MAX * ( max - min ) + min );

}

double get_random_double_value( const double min, const double max ){

  return ( double ) rand() / RAND_MAX * ( max - min ) + min;

}

double gaussrand( const double mu, const double sigma ){

  return ( sqrt( -2 * log( get_random_double_value( 0.0, 1.0 ) ) )
	   * sin( 2 * M_PI * get_random_double_value( 0.0, 1.0 ) ) * sigma + mu );

}


double calc_var( const double* array, const int num ){
  int i;
  double sum;
  double average;

  if( num == 1 )
    return 0.0;

  else{
    sum = 0.0;
    for( i=0; i<num; i++ ){
      sum += array[ i ];
    }
  
    average = sum / num;
    
    sum = 0.0;
    for( i=0; i<num; i++ ){
      sum += pow( ( average - array[ i ] ), 2 );
    }

    //    return sum / (num-1);
    return sum / num ;
  }
}

void print_value(){
  int i, j;

  for( i = 0; i < number_of_layers; i++ )
    {
      printf( ":%02d\t%d\t", i, number_of_generations );
      for( j = 0; j < each_individuals; j++)
        {
          printf( "%f\t", layers[ i ].individuals[ j ].function_value );
	}
      printf("\n");
    }

}


void print_individuals(){
  int i, j, k;

  for( i = 0; i < number_of_layers; i++ )
    {
      for( j = 0; j < each_individuals; j++)
	{

	  printf( "%d\t%f\t: ", i, layers[ i ].individuals[ j ].function_value );

	  for( k = 0; k < number_of_dimensions; k++){

	    printf( "%f ", layers[ i ].individuals[ j ].design_variables[ k ] );

	  }

	  printf( "\n" );
	}
    }
}

void print_sigma(){
  int i, j;

  for( i=0; i<number_of_layers; i++ )
    {
      printf( "SIGMA:Gen:%d:Layer:%02d\t", number_of_generations , i );

      for( j=0; j<number_of_dimensions; j++ )
        {
          printf( "%.5f\t", layers[ i ].sigma[ j ] );
        }
      printf( "\n" );
    }

}

void print_center(){
  int i, j;

  for( i=0; i<number_of_layers; i++ )
    {
      printf( "CENTER:Gen:%d:Layer:%d\t", number_of_generations , i );

      for( j=0; j<number_of_dimensions; j++ )
        {
          printf( "%.5f\t", layers[ i ].center[ j ] );
        }
      printf( "\n" );
    }

}


int terminate(){
  int i, j;

  if( ( strcmp( function_name, "f1" ) == 0 ) || ( strcmp( function_name, "f2" ) == 0 ) | ( strcmp( function_name, "f3" ) == 0 ) ){

    for( i = 0; i < number_of_layers; i++ ){
      for( j = 0; j <  each_individuals; j++ ){

	if ( termination_eps - 0.001 < layers[ i ].individuals[ j ].function_value ){
	  printf( "[Find_Result] ");
	  print_best();
	  
	  return 1;
	}

      }
    } // end for

  } else{

    for( i = 0; i < number_of_layers; i++ ){
      for( j = 0; j <  each_individuals; j++ ){

        if ( termination_eps > layers[ i ].individuals[ j ].function_value ){
          printf( "[Find_Result] ");
          print_best();

          return 1;
        }

      }
    } // end for
  }


  // Limit of Evaluation
  if( number_of_evaluations > max_evaluations ){
    printf( "[Max_Evaluation] ");
    print_best();
    
    return 1;

  } else{
    return 0;
  }

}


void print_best(){
  int i, j, k;
  INDIVIDUAL elite[ each_individuals * number_of_layers ];

  // copy
  for( i = 0; i < number_of_layers; i++ ){
    for( j = 0; j < each_individuals; j++ ){
      elite[ i * each_individuals + j ].function_value = layers[ i ].individuals[ j ].function_value;
      elite[ i * each_individuals + j ].design_variables = ( double * ) malloc( sizeof( double ) * number_of_dimensions );

      for( k = 0; k < number_of_dimensions; k++ ){
	elite[ i * each_individuals + j ].design_variables[ k ] = layers[ i ].individuals[ j ].design_variables[ k ];
      }
    }
  }

  population_sort( elite, number_of_layers * each_individuals );

  if( msg_type == 1 ){
    if( number_of_generations == 1 )
      printf( "Gen.\tEva.\t\tValue\t\tDesigin Variables\n");

    printf( ": %5d\t%8d\t%.3e\t", number_of_generations, number_of_evaluations, elite[ 0 ].function_value );

    for( i = 0; i < number_of_dimensions; i++ )
      printf( "%.4f\t", elite[ 0 ].design_variables[ i ] );
      
    printf( "\n" );
  } else{
    if( number_of_generations == 1 )
      printf( "Gen.\tEva.\t\tValue\n" );

    printf( ":%5d\t%8d\t%.3e\n", number_of_generations, number_of_evaluations, elite[ 0 ].function_value );
  }

  // free
  for( i = 0; i < number_of_layers * each_individuals; i++ ){
      free( elite[ i ].design_variables );
  }

}
